package com.miplus.ccrm.core.service.voiceprint;

import com.miplus.ccrm.common.EnumRCode;
import com.miplus.ccrm.common.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author： Yaohui
 * @Date： 2025/3/1 16:27
 * @Describe：
 */
@Service
@Slf4j
public class VoicelibraryService {

    @Value("${voice.library.url}")
    private String vUrl;

    @Value("${voice.library.port}")
    private String vPort;


    /**
     * 声纹确认
     * @param businessId
     * @return
     */
    public Double verifymodel(String businessId,File file){
        String userid=businessId;
        String token =getToken(businessId);

        try {
            //定义数据分隔符
            String TWO_HYPHENS = "--";
            String BOUNDARY = "*****";
            String END = "\r\n";
            String CHARSET = "UTF-8";

            //上传语音
            String ht=vUrl+":"+vPort;
            URL url = new URL(ht+"/verifymodel");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Charsert", "UTF-8");
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

            HashMap<String, String> param = null;
            param = new HashMap<String, String>();
            param.put("userid", userid); //必选字段
            param.put("token", token); //必选字段
            param.put("content", "123456");//设置语音对应文本，必选字段

            OutputStream out = new DataOutputStream(conn.getOutputStream());
            byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();// 定义最后数据分隔线

            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> entry : param.entrySet()) {
                sb.append(TWO_HYPHENS);
                sb.append(BOUNDARY);
                sb.append(END);
                sb.append("Content-Disposition: form-data; name=\""
                        + entry.getKey() + "\"" + END);
                sb.append("Content-Type: text/plain; charset=" + CHARSET + END);
                sb.append("Content-Transfer-Encoding: 8bit" + END);
                sb.append(END);
                sb.append(entry.getValue());
                sb.append(END);
            }

            //------
            sb.append("--");
            sb.append(BOUNDARY);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data;name=\"file\";filename=\""+ file.getName() + "\"\r\n");
            sb.append("Content-Type:application/octet-stream\r\n\r\n");

            byte[] data = sb.toString().getBytes();
            out.write(data);
            DataInputStream in = new DataInputStream(new FileInputStream(file));
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
            out.write("\r\n".getBytes()); //多个文件时，二个文件之间加入这个
            in.close();
            //------

            out.write(end_data);
            out.flush();
            out.close();

            // 定义BufferedReader输入流来读取URL的响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = null;
            String rs="";
            while ((line = reader.readLine()) != null) {
                log.info(line);
                rs=rs+line;
            }
            JSONObject jsonObject=new JSONObject(rs);
            int code= (Integer) jsonObject.get("errCode");
            if(code==0){
                Double score= new Double(jsonObject.get("score").toString()) ;
                log.info("score:{}",score);
                return score;
            }else {
                throw new ServiceException(EnumRCode.VerifyModelError.value, EnumRCode.VerifyModelError.name);
            }
        } catch (Exception e) {
            log.error("发送POST请求出现异常！" + e);
            e.printStackTrace();
        }

        return 0.0;
    }

    /**
     * 训练模型
     * @return
     */
    public int trainmodel(String businessId){

        // 只有上传一条有效语音达到20s以上的录音文件，才能训练模型。
        try {
            //定义数据分隔符
            String TWO_HYPHENS = "--";
            String BOUNDARY = "*****";
            String END = "\r\n";
            String CHARSET = "UTF-8";

            //训练模型userid
            String userid = businessId;
            String token = getToken(businessId);

            String ht=vUrl+":"+vPort;
            String str_url = ht+"/trainmodel?userid=" + userid + "&token=" + token;
            log.info("str_url:{}",str_url);
            URL url = new URL(str_url);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Charsert", "UTF-8");
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

            // 定义BufferedReader输入流来读取URL的响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = null;
            String rs="";
            while ((line = reader.readLine()) != null) {
                log.info(line);
                rs=rs+line;
            }
            JSONObject jsonObject=new JSONObject(rs);
            int code= (Integer) jsonObject.get("errCode");
            return code;
        } catch (Exception e) {
            log.error("发送POST请求出现异常！:{}",e);
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 添加录音
     * @param businessId
     */
    public int addSample(String businessId, Integer step, File file){

        try {

            String TWO_HYPHENS = "--";
            String BOUNDARY = "*****";
            String END = "\r\n";
            String CHARSET = "UTF-8";

            String ht=vUrl+":"+vPort;
            URL url = new URL(ht+"/addsample");
//            URL url = new URL("http://10.144.147.29:9362/addsample");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Charsert", "UTF-8");
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

            HashMap<String, String> param = null;
            param = new HashMap<String, String>();
            param.put("userid", businessId);
            param.put("token", getToken(businessId));
            param.put("step", String.valueOf(step));
            param.put("content", "123456");
            param.put("sampleRate", "16000");
            param.put("bits", "16");
            param.put("channels", "1");

            OutputStream out = new DataOutputStream(conn.getOutputStream());
            byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();// 定义最后数据分隔线
            StringBuilder sb = new StringBuilder();

            for (Map.Entry<String, String> entry : param.entrySet()) {
                sb.append(TWO_HYPHENS);
                sb.append(BOUNDARY);
                sb.append(END);
                sb.append("Content-Disposition: form-data; name=\""
                        + entry.getKey() + "\"" + END);
                sb.append("Content-Type: text/plain; charset=" + CHARSET + END);
                sb.append("Content-Transfer-Encoding: 8bit" + END);
                sb.append(END);
                sb.append(entry.getValue());
                sb.append(END);
            }

            // ----
            sb.append("--");
            sb.append(BOUNDARY);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data;name=\"file\";filename=\""+ file.getName() + "\"\r\n");
            sb.append("Content-Type:application/octet-stream\r\n\r\n");
            byte[] data = sb.toString().getBytes();
            out.write(data);
            DataInputStream in = new DataInputStream(new FileInputStream(file));
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
            out.write("\r\n".getBytes()); //多个文件时，二个文件之间加入这个
            in.close();
            // ----
            out.write(end_data);
            out.flush();
            out.close();
            log.info("conn.getResponseMessage():{}",conn.getResponseMessage());
            log.info("conn.getResponseCode():{}",conn.getResponseCode());
            if(conn.getResponseCode()!=200){
                return -1;
            }
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = null;
            String rs="";
            while ((line = reader.readLine()) != null) {
                log.info(line);
                rs=rs+line;
            }
            JSONObject jsonObject=new JSONObject(rs);
            int code= (Integer) jsonObject.get("errCode");
            return code;
        }  catch (Exception e) {
            log.error(e.getMessage());
            e.printStackTrace();
        }
        return -1;

    }


    private String getToken(String businessId){
        return businessId.substring(businessId.length()-4);
    }
}
